package myserver

import (
	"fmt"
	"io"
	"net"
	"sync"
	"time"
)

const CONN_BUFFER_SIZE uint = 1024
const MAXTIME uint = 300

type Server struct {
	ip        string
	port      int
	OnlineMap map[string]*User
	mapLock   sync.RWMutex
	Message   chan string
}

func NewServer(ip string, port int) *Server {
	return &Server{
		ip:        ip,
		port:      port,
		OnlineMap: make(map[string]*User),
		Message:   make(chan string),
	}
}

func (server *Server) Handler(conn net.Conn) {
	user := NewUser(conn, server)
	user.Online()

	fmt.Printf(user.GetUserinfo() + "connection established\n")

	chanlive := make(chan bool)

	go func() {
		buff := make([]byte, CONN_BUFFER_SIZE)
		for {
			n, err := conn.Read(buff)
			if n == 0 {
				user.Offline()
				fmt.Println(user.GetUserinfo() + "offline")
				return
			} else if err != nil && err != io.EOF {
				fmt.Println("conn read err: ", err)
				return
			} else {
				msg := string(buff)[:n-1]
				fmt.Println(user.GetUserinfo() + "request \"" + msg + "\"")
				user.DoMessage(msg)
				chanlive <- true
			}
		}
	}()
	for {
		select {
		case <-chanlive:
		case <-time.After(time.Second * time.Duration(MAXTIME)):
			tmp_s := user.GetUserinfo() + "auto closed\n"
			user.SendMessage(tmp_s)
			fmt.Printf("%s", tmp_s)
			user.Close()
			return

		}
	}
}

func (server *Server) Broadcast(msg string) {
	server.Message <- msg
}

func (server *Server) ListenMessage() {
	var msg string
	for {
		msg = <-server.Message
		server.mapLock.RLock()
		for _, cli := range server.OnlineMap {
			cli.Channel <- msg
		}
		server.mapLock.RUnlock()
	}
}

func (server *Server) Start() {
	listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", server.ip, server.port))
	if err != nil {
		fmt.Println("net.Listen err: ", err)
		return
	}
	defer listener.Close()

	go server.ListenMessage()

	for {
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println("listener.Accept err: ", err)
			continue
		}

		go server.Handler(conn)

	}
}
